﻿#pragma execution_character_set("utf-8")
#include "acqure.h"
#include <QTimer>
#include <QDebug>
#define sys_log qDebug()

Acqure::Acqure(QObject *parent, HANDLE dev_handle)
    : QObject(parent)
    , hDevice(dev_handle)
{
    QTimer::singleShot(500, this, &Acqure::DEV_Init);
}
Acqure::~Acqure()
{
    if(hDevice != INVALID_HANDLE_VALUE)
    {
        AI_StopTask();// 第六步 停止AI采样
        AI_ReleaseTask();// 第七步 释放AI采集任务
        DEV_Release();// 第八步 释放设备对象
    }
}
bool Acqure::DEV_Init()// 创建设备后进行设备初始化
{

    if(!Port_Config())
        return false;
    emit out_log("AI first init ok.");
    return true;
}

/*-------------------------------参数调整------------------------------------*/
void Acqure::select_RefGround(int index)    //接线方式
{
    switch (index)
    {
    case 0:
    {
        RefGround = USB5630_AI_REFGND_RSE;//参考地
        emit out_log("接线方式设置为参考地.");
        break;
    }
    case 1:
    {
        RefGround = USB5630_AI_REFGND_NRSE;//参考地
        emit out_log("接线方式设置为无参考地.");
        break;
    }
    case 2:
    {
        RefGround = USB5630_AI_REFGND_DIFF;//参考地
        emit out_log("接线方式设置为差分.");
        break;
    }
    }
}
void Acqure::select_SampleRange(int index)  //采样范围
{
    switch (index)
    {
    case 0:
    {
        SampleRange = USB5630_AI_SAMPRANGE_N10_P10V;//采样范围
        emit out_log("采样范围设置-10V~10V.");
        break;
    }
    case 1:
    {
        SampleRange = USB5630_AI_SAMPRANGE_N5_P5V;
        emit out_log("采样范围设置-5V~5V.");
        break;
    }
    case 2:
    {
        SampleRange = USB5630_AI_SAMPRANGE_N2D5_P2D5V;
        emit out_log("采样范围设置-2.5V~2.5V.");
        break;
    }
    case 3:
    {
        SampleRange = USB5630_AI_SAMPRANGE_0_P10V;
        emit out_log("采样范围设置0V~10V.");
        break;
    }
    case 4:
    {
        SampleRange = USB5630_AI_SAMPRANGE_0_P5V;
        emit out_log("采样范围设置0V~5V.");
        break;
    }
    }
}
void Acqure::change_SampleRate(double value)    //采样速率
{
    SampleRate	= value;//采样速率
    emit out_log(QString("采样速率设置为%1.").arg(value) );
}
void Acqure::change_SampChanCount(int count)    //采样通道总数
{
    dataColumns = count;
    emit out_log(QString("采样通道总数设置为%1.").arg(count) );
}
void Acqure::change_SampsPerChan(int count) //每通道采样点数
{

    if(count < 2)   //单点采集模式下采样点数不小于2，否则AI_VerifyParam报错并自动调整为2。实际采集点数为1
    {
       dataRows = 2;
       emit out_log(QString("每通道采样点数设置为2."));
       return;
    }
    dataRows = count;//每通道采样点数
    emit out_log(QString("每通道采样点数设置为%1.").arg(count) );
}
/*-------------------------------设备操作------------------------------------*/

bool Acqure::Port_Config()    //端口配置，端口功能、方向、值等参数
{
    memset(&PortParam, 0, sizeof(PortParam));
    for (int nIdx=0; nIdx<8; nIdx++)	// 端口0
    {
        PortParam.CHParam[0].nFunction[nIdx] = USB5630_PORT_FUN_DIO;	// 端口0只能为DIO
        PortParam.CHParam[0].nDIODir[nIdx] = USB5630_PORT_DIR_DO;	// 置为DO
        PortParam.CHParam[0].nDIOVal[nIdx] = 0;	// nDIODir为输出时有效
    }
    for (int nIdx=0; nIdx<8; nIdx++)	// 端口1(PFI0~7)
    {
        PortParam.CHParam[1].nFunction[nIdx] = USB5630_PORT_FUN_CTR;	// 端口1设为CTR功能
    }
    for (int nIdx=0; nIdx<4; nIdx++)	// 端口2(PFI8~15)
    {
        PortParam.CHParam[2].nFunction[nIdx*2] = USB5630_PORT_FUN_PFIIN;// 端口2(0 2 4 6设为PFI输入)
        PortParam.CHParam[2].nFunction[nIdx*2+1] = USB5630_PORT_FUN_PFIOUT;// 端口2(1 3 5 7设为PFI输出)
    }

    if (!USB5630_Port_Config(hDevice, &PortParam))
    {
        emit out_log(QString("Port_Config Error, code:%1, please refer to the sys.log").arg(GetLastError()));
        USB5630_DEV_Release(hDevice);
        return false;
    }
    emit out_log("Port_Config ok.所有参数已生效.");
    return true;
}
bool Acqure::AI_VerifyParam()    //AI工作参数结构体配置
{
    memset(&AIParam, 0, sizeof(USB5630_AI_PARAM));//AIParam初始化为0
    // 通道参数
    AIParam.nSampChanCount = dataColumns;//采样通道总数
    for(int nChannel=0; nChannel<USB5630_AI_MAX_CHANNELS; nChannel++)//所有通道的参数配置
    {
        AIParam.CHParam[nChannel].nChannel		= nChannel;//AI物理通道号
        AIParam.CHParam[nChannel].nSampleGain	= USB5630_AI_SAMPGAIN_1MULT;//采样增益
        AIParam.CHParam[nChannel].nRefGround	= RefGround;//参考地
        AIParam.CHParam[nChannel].nReserved0	= 0;//保留字段
        AIParam.CHParam[nChannel].nReserved1	= 0;
        AIParam.CHParam[nChannel].nReserved2	= 0;
    }
    AIParam.nChanScanMode			= USB5630_AI_CHAN_SCANMODE_CONTINUOUS;//扫描模式
    AIParam.nGroupLoops				= 1;//每个通道组循环次数
    AIParam.nGroupInterval			= 1;//每两个通道组间的时间间隔，微秒
    AIParam.nSampleSignal			= USB5630_AI_SAMPSIGNAL_AI;//采样信号
    AIParam.nSampleRange			= SampleRange;//采样范围
    AIParam.nClockSource			= USB5630_AIO_CLKSRC_LOCAL;//时钟源
    AIParam.nClockOutput			= USB5630_AIO_CLKOUT_DISABLE;//是否输出采样时钟

    // 时钟参数
    AIParam.fSampleRate				= SampleRate;//最高采样速率=500k/通道总数
    AIParam.nSampleMode				= USB5630_AI_SAMPMODE_ONE_DEMAND;//采样模式，单点
    AIParam.nSampsPerChan			= 2;//每通道采样点数

    // 触发参数
    AIParam.bDTriggerEn				= TRUE;//数字触发使能
    AIParam.nDTriggerDir			= USB5630_AI_TRIGDIR_FALLING;//触发方向，上升/下降沿
    AIParam.nDTrigChannel			= USB5630_AIO_DTRIG_PFI08;//触发通道

    AIParam.bATriggerEn				= TRUE;//模拟触发使能
    AIParam.nATriggerDir			= USB5630_AI_TRIGDIR_FALLING;//触发方向，上升/下降沿
    AIParam.fTriggerLevel			= 0.0;//触发电平
    AIParam.nTriggerSens			= 5;//触发灵敏度，微秒

    // 其他参数
    AIParam.nReserved1				= 0;//保留字段
    AIParam.nReserved2				= 0;
    AIParam.nReserved3				= 0;

    if(!USB5630_AI_VerifyParam(hDevice, &AIParam))
    {
        emit out_log("Parameter error, it has been adjusted to a valid value, please check the log file USB5630.log");
    }
    emit out_log("AI_VerifyParam ok!");
    nReadSampsPerChan = AIParam.nSampsPerChan;//每通道请求读入的数据点数
    return true;
}
bool Acqure::AI_InitTask()// 第二步 初始化AI采样任务
{
    if(!USB5630_AI_InitTask(hDevice, &AIParam, NULL))
    {
        emit out_log(QString("AI_InitTask Error,code:%1").arg(GetLastError()));
        USB5630_DEV_Release(hDevice);
        return false;
    }
    emit out_log("AI_InitTask ok.");
    return true;
}

bool Acqure::AI_StartTask()// 第三步 启动AI采样任务
{
    if(!USB5630_AI_StartTask(hDevice))
    {
        emit out_log(QString("AI_StartTask Error,code:%1").arg(GetLastError()));
        return false;
    }
    emit out_log("AI_StartTask ok.");
    return true;
}

bool Acqure::AI_SendSoftTrig()// 第四步 发送软件触发事件(硬件外触发时不需要)
{
    if(!USB5630_AI_SendSoftTrig(hDevice))
    {
        emit out_log(QString("AI_SendSoftTrig Error,code:%1").arg(GetLastError()));
        return false;
    }
    return true;
}
bool Acqure::AI_ReadBinary()// 第五步 循环读取AI数据
{
    if(!AI_SendSoftTrig())
        return false;
    if(!USB5630_AI_ReadBinary(hDevice, nBinArray, nReadSampsPerChan, &nSampsPerChanRead, &nReadableSamps, fTimeout))
    {
        emit out_log(QString("Timeout nSampsPerChanRead=%1\n").arg(nSampsPerChanRead));
        return false;
    }
    for(U16 nChannel=0; nChannel<AIParam.nSampChanCount; nChannel++)
    {
        emit out_log(QString("Channel:%1,Value:%2\n").arg(nChannel).arg(nBinArray[nChannel]));
    }
    AI_StopTask();// 第六步 停止AI采样
    AI_ReleaseTask();// 第七步 释放AI采集任务
    return true;
}

void Acqure::loop_read()
{
    isReading = true;
    U8 nPortData = 0x00;
    cv::Mat mat(dataRows, AIParam.nSampChanCount, CV_16UC1);
    emit out_log("loop_read begin.");
    while(1)
    {
        if(!isReading)
            break;
        nPortData = 0x40;
        for(int i = 0; i < dataRows; i++) //矩阵的列
        {
            if(!USB5630_DIO_WritePort(hDevice, 0, nPortData++))
                cout<<"WritePort error"<<endl;
            if(!AI_SendSoftTrig())
            {
                emit out_log("AI_SendSoftTrig error,loop_read quit.");
                return;
            }
            USB5630_AI_ReadBinary(hDevice, nBinArray, nReadSampsPerChan, &nSampsPerChanRead, &nReadableSamps, fTimeout);
            for(int j = 0; j < AIParam.nSampChanCount; j++)    //矩阵的行
            {
                mat.at<unsigned short>(i, j) = nBinArray[j];
            }
        }
        signal_mat = mat.clone();
        emit out_mat(signal_mat);
    }
    AI_StopTask();
    AI_ReleaseTask();
    emit out_log("loop_read end.");
}

void Acqure::stop_loop_read()
{
    isReading = false;
}

bool Acqure::AI_StopTask()// 第六步 停止AI采样
{
    if(!USB5630_AI_StopTask(hDevice))
    {
        emit out_log(QString("AI_StopTask Error,code:%1").arg(GetLastError()));
        return false;
    }
    emit out_log("AI_StopTask ok.");
    return true;
}
bool Acqure::AI_ReleaseTask()// 第七步 释放AI采集任务
{
    if(!USB5630_AI_ReleaseTask(hDevice))
    {
        emit out_log(QString("AI_ReleaseTask Error,code:%1").arg(GetLastError()));
        return false;
    }
    emit out_log("AI_ReleaseTask ok.");
    return true;
}
bool Acqure::DEV_Release()// 第八步 释放设备对象
{
    if(!USB5630_DEV_Release(hDevice))
    {
        emit out_log(QString("DEV_Release Error,code:%1").arg(GetLastError()));
        return false;
    }
    emit out_log("DEV_Release ok.");
    return true;
}
